package com.douya.common.utils;

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 说明:RestTemplate工具类,用来http请求
 * ConnectTimeout
 * 指的是建立连接所用的时间，适用于网络状况正常的情况下，两端连接所用的时间。
 * 在java中，网络状况正常的情况下，例如使用HttpClient或者HttpURLConnetion连接时设置参数connectTimeout=5000即5秒，如果连接用时超过5秒就是抛出java.net.SocketException: connetct time out的异常。
 * ReadTimeout
 * 指的是建立连接后从服务器读取到可用资源所用的时间。
 * 在这里我们可以这样理解ReadTimeout：正常情况下，当我们发出请求时可以收到请求的结果，也就是页面上展示的内容，但是当网络状况很差的时候，就会出现页面上无法展示出内容的情况。另外当我们使用爬虫或者其他全自动的程序时，无法判断当前的网络状况是否良好，此时就有了ReadTimeout的用武之地了，通过设置ReadTimeout参数，例：ReadTimeout=5000，超过5秒没有读取到内容时，就认为此次读取不到内容并抛出Java.net.SocketException: read time out的异常。
 * 根据上面关于ConnectTimeout和ReadTimeout的描述，在我们使用需要设置这两项参数的服务或程序时，应该对两项参数一起设置。
 * 一般而言两项参数的数值可以设置成一样的，但根据笔者个人经验，可以把ReadTimeout设置的长一点，ConnectTimeout可以相对比较短，这是源于我们的网络状况一般较为稳定，连接时很少出现问题，但是读取时因为数据下载时的网络波动，出状况的可能性更大一些。
 *
 * @Author 胡晨烨
 * @Date 2020/2/28
 */
public class RestTemplateUtils {


    /**
     * @return 返回了设置连接超时的RestTemplate
     */
    public static RestTemplate getCommonRestTemplate() {
        return getCommonRestTemplate(10000, 10000);
    }


    /**
     * @return 返回了设置连接超时的RestTemplate
     */
    public static RestTemplate getCommonRestTemplate(int connectTimeout, int readTimeout) {
        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

        MediaType[] mediaTypes = new MediaType[]{
                MediaType.APPLICATION_JSON,
                MediaType.APPLICATION_OCTET_STREAM,

                MediaType.TEXT_HTML,
                MediaType.TEXT_PLAIN,
                MediaType.TEXT_XML,
                MediaType.APPLICATION_STREAM_JSON,
                MediaType.APPLICATION_ATOM_XML,
                MediaType.APPLICATION_FORM_URLENCODED,
                MediaType.APPLICATION_JSON_UTF8,
                MediaType.APPLICATION_PDF,
        };
        converter.setSupportedMediaTypes(Arrays.asList(mediaTypes));
        messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
        messageConverters.add(new FormHttpMessageConverter());
        messageConverters.add(converter);
        RestTemplate restTemplate = new RestTemplate(messageConverters);
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        HttpClient httpClient = HttpClientBuilder.create()
                .setRedirectStrategy(new LaxRedirectStrategy())
                .build();
        requestFactory.setHttpClient(httpClient);
        requestFactory.setConnectTimeout(connectTimeout);
        requestFactory.setReadTimeout(readTimeout);
        restTemplate.setRequestFactory(requestFactory);
        return restTemplate;
    }

}
